🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / app / src / main / java / com / geeksville / mesh / android / ServiceClient.kt
Displaying Raw • Download
app/src/main/java/com/geeksville/mesh/android/ServiceClient.kt 78274c792318331b11ab64cd28e58e829875b8c2 (78274c79) Text, 4.63 KB
T8b949e/*
* Copyright (c) 2025 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787com.geeksville.mesh.android
Tff7b72import T7ee787android.content.ComponentName
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.content.ServiceConnection
Tff7b72import T7ee787android.os.IBinder
Tff7b72import T7ee787android.os.IInterface
Tff7b72import T7ee787com.geeksville.mesh.util.exceptionReporter
Tff7b72import T7ee787timber.log.Timber
Tff7b72import T7ee787java.io.Closeable
Tff7b72import T7ee787java.lang.IllegalArgumentException
Tff7b72import T7ee787java.util.concurrent.locks.ReentrantLock
Tff7b72import T7ee787kotlin.concurrent.withLock
Tff7b72class T56d364BindFailedException Tb4b4b4: Te6edf3ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffbindService failedTa5d6ff"Tb4b4b4)
T8b949e/** A wrapper that cleans up the service binding process */
Tff7b72open Tff7b72class T56d364ServiceClientTff7b72<Te6edf3T Tb4b4b4: Te6edf3IInterfaceTff7b72>Tb4b4b4(Tff7b72private Tff7b72val Te6edf3stubFactoryTb4b4b4: Tb4b4b4(Te6edf3IBinderTb4b4b4) Tff7b72-Tff7b72> Te6edf3TTb4b4b4) Tb4b4b4: Te6edf3Closeable Tb4b4b4{
Tff7b72var Te6edf3servicePTb4b4b4: Te6edf3T? Tff7b72= Tff7b72null
T8b949e// A getter that returns the bound service or throws if not bound
Tff7b72val Te6edf3serviceTb4b4b4: Te6edf3T
Tff7b72getTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3waitConnectTb4b4b4(Tb4b4b4) T8b949e// Wait for at least the initial connection to happen
Tff7b72return Te6edf3serviceP Tff7b72?: Tff7b72throw Te6edf3ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffService not boundTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3contextTb4b4b4: Te6edf3Context? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3isClosed Tff7b72= Tff7b72true
Tff7b72private Tff7b72val Te6edf3lock Tff7b72= Te6edf3ReentrantLockTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3condition Tff7b72= Te6edf3lockTb4b4b4.Te6edf3newConditionTb4b4b4(Tb4b4b4)
T8b949e/** Call this if you want to stall until the connection is completed */
Tff7b72fun Td2a8ffwaitConnectTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Wait until this service is connected
Te6edf3lockTb4b4b4.Te6edf3withLock Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3context Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffHaven't called connectTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3serviceP Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3conditionTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffconnectTb4b4b4(Te6edf3cTb4b4b4: Te6edf3ContextTb4b4b4, Te6edf3intentTb4b4b4: Te6edf3IntentTb4b4b4, Te6edf3flagsTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3context Tff7b72= Te6edf3c
Tff7b72if Tb4b4b4(Te6edf3isClosedTb4b4b4) Tb4b4b4{
Te6edf3isClosed Tff7b72= Tff7b72false
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3cTb4b4b4.Te6edf3bindServiceTb4b4b4(Te6edf3intentTb4b4b4, Te6edf3connectionTb4b4b4, Te6edf3flagsTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// Some phones seem to ahve a race where if you unbind and quickly rebind bindService returns false.
T8b949e// Try
T8b949e// a short sleep to see if that helps
Te6edf3TimberTb4b4b4.Te6edf3eTb4b4b4(Ta5d6ff"Ta5d6ffNeeded to use the second bind attempt hackTa5d6ff"Tb4b4b4)
Te6edf3ThreadTb4b4b4.Te6edf3sleepTb4b4b4(T79c0ff5T79c0ff0T79c0ff0Tb4b4b4) T8b949e// was 200ms, but received an autobug from a Galaxy Note4, android 6.0.1
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3cTb4b4b4.Te6edf3bindServiceTb4b4b4(Te6edf3intentTb4b4b4, Te6edf3connectionTb4b4b4, Te6edf3flagsTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3BindFailedExceptionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3TimberTb4b4b4.Te6edf3wTb4b4b4(Ta5d6ff"Ta5d6ffIgnoring rebind attempt for serviceTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffcloseTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3isClosed Tff7b72= Tff7b72true
Tff7b72try Tb4b4b4{
Te6edf3contextTff7b72?.Te6edf3unbindServiceTb4b4b4(Te6edf3connectionTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3IllegalArgumentExceptionTb4b4b4) Tb4b4b4{
T8b949e// Autobugs show this can generate an illegal arg exception for "service not registered" during reinstall?
Te6edf3TimberTb4b4b4.Te6edf3wTb4b4b4(Ta5d6ff"Ta5d6ffIgnoring error in ServiceClient.close, probably harmlessTa5d6ff"Tb4b4b4)
Tb4b4b4}
Te6edf3serviceP Tff7b72= Tff7b72null
Te6edf3context Tff7b72= Tff7b72null
Tb4b4b4}
T8b949e// Called when we become connected
Tff7b72open Tff7b72fun Td2a8ffonConnectedTb4b4b4(Te6edf3serviceTb4b4b4: Te6edf3TTb4b4b4) Tb4b4b4{Tb4b4b4}
T8b949e// called on loss of connection
Tff7b72open Tff7b72fun Td2a8ffonDisconnectedTb4b4b4(Tb4b4b4) Tb4b4b4{Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3connection Tff7b72=
Tff7b72object Tb4b4b4: T56d364ServiceConnection Tb4b4b4{
Tff7b72override Tff7b72fun Td2a8ffonServiceConnectedTb4b4b4(Te6edf3nameTb4b4b4: Te6edf3ComponentNameTb4b4b4, Te6edf3binderTb4b4b4: Te6edf3IBinderTb4b4b4) Tff7b72= Te6edf3exceptionReporter Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isClosedTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3s Tff7b72= Te6edf3stubFactoryTb4b4b4(Te6edf3binderTb4b4b4)
Te6edf3serviceP Tff7b72= Te6edf3s
Te6edf3onConnectedTb4b4b4(Te6edf3sTb4b4b4)
T8b949e// after calling our handler, tell anyone who was waiting for this connection to complete
Te6edf3lockTb4b4b4.Te6edf3withLock Tb4b4b4{ Te6edf3conditionTb4b4b4.Te6edf3signalAllTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// If we start to close a service, it seems that there is a possibility a onServiceConnected event
T8b949e// is the queue
T8b949e// for us. Be careful not to process that stale event
Te6edf3TimberTb4b4b4.Te6edf3wTb4b4b4(Ta5d6ff"Ta5d6ffA service connected while we were closing it, ignoringTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffonServiceDisconnectedTb4b4b4(Te6edf3nameTb4b4b4: Te6edf3ComponentName?Tb4b4b4) Tff7b72= Te6edf3exceptionReporter Tb4b4b4{
Te6edf3serviceP Tff7b72= Tff7b72null
Te6edf3onDisconnectedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.05s